Consider transitive fingerprints for freshness
authorAlex Crichton <alex@alexcrichton.com>
Thu, 29 Jan 2015 03:37:19 +0000 (19:37 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 29 Jan 2015 06:01:35 +0000 (22:01 -0800)
commita40d3b03b8afb06187447c7607c928e13241f846
tree442254c32d5b5f9d5a3c773ed7164ad15220c50c
parent453ae9f268c7e41c25012514eb5c502a3711e480
Consider transitive fingerprints for freshness

Originally discovered through #1236, this commit fixes a bug in Cargo where
crates may not be recompiled when they need to (leading to obscure errors from
the compiler). The scenario in question looks like:

* Assume a dependency graph of `A -> B -> C` and `A -> C`
* Build all packages
* Modify C
* Rebuild, but hit Ctrl+C while B is building
* Modify A
* Rebuild again

Previously, Cargo only considered the freshness of a package to be the freshness
of the package itself (checking source files, for example). To handle transitive
recompilations, Cargo propagates a dirty bit throughout the dependency graph
automatically (instead if calculating it as such).

In the above example, however, we have a problem where as part of the last
rebuild Cargo thinks `B` and `C` are fresh! The artifact for `C` was just
recompiled, but `B`'s source code is untainted, so Cargo does not think that it
needs to recompile `B`. This is wrong, however, because one of `B`'s
dependencies was rebuilt, so it needs to be rebuilt.

To fix this problem, the fingerprint (a short hash) for all packages is now
transitively propagated (the fingerprint changes when an upstream package
changes). This should ensure that even when Ctrl+C is hit (or the situation
explained in #1236) that Cargo will still consider packages whose source code is
untainted as candidates for recompilation.

The implementation is somewhat tricky due to the actual fingerprint for a path
dependency not being known until *after* the crate is compiled (the fingerprint
is the mtime of the dep-info file).

Closes #1236
src/cargo/core/manifest.rs
src/cargo/core/package_id.rs
src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/fingerprint.rs
src/cargo/ops/cargo_rustc/mod.rs
tests/support/paths.rs
tests/test_cargo_cross_compile.rs
tests/test_cargo_freshness.rs
tests/test_cargo_test.rs